package com.infindo.appcreate.thread.queue;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public  class  ThreadManager<T> extends Thread implements ThreadCallback {
	
	private int maxThread = 2;
	private Map<Long, TaskThread> threadActiveList = new HashMap<Long, TaskThread>();
	private List<T> taskList;
	private  static  ThreadManager  instance = null;
	
	private boolean running = true;
	private boolean taskExecuting = false;
	
    public synchronized  static <T> ThreadManager<T> getInstance(T t) {
    	if (instance == null) {
			instance = new ThreadManager<T>();
		    instance.start();
		    
		}
		return instance;
	}
	
    public void setMaxThread(int threadCount) {
        maxThread = threadCount;
    }
	   
	private ThreadManager() {
	}
	
    public boolean isTaskExecuting() {
        if (taskList == null || taskList.isEmpty()) {
            if (threadActiveList == null || threadActiveList.isEmpty()) {
                taskExecuting = false;
            }
        }
        return taskExecuting;
    }
	
	public synchronized void addTask(T task) {
	    if (taskList == null)
	        taskList = new ArrayList<T>();
	    taskList.add(task);
	    notifyMe();
	}
	
    public synchronized void addAllTask(List<T> taskList) {
        this.taskList = taskList;
        notifyMe();
    }
	   
    private synchronized void notifyMe() {
        this.notify();
    }
    
    public void run() {
        synchronized(this) {
            
                while (running) {
                    try {
                        taskExecuting = true;
                        if (taskList == null || taskList.isEmpty()) {
                            if (threadActiveList.size() == 0) {
                                taskExecuting = false;
                                System.out.println("++++==============all task ended or no task start yet!");
                            }
                            this.wait();
                        } else {
                            if (threadActiveList.size() >= maxThread) {
                                this.wait();
                            } else {
                            	
                                try {
                                    T r = taskList.get(0);
                                    taskList.remove(0);
                                    TaskThread  taskThread = new TaskThread (this, r);
                                    threadActiveList.put(taskThread.getId(), taskThread);
                                    taskThread.start();
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                                System.out.println("threadActiveList.size() " + threadActiveList.size());
                            }
    
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    
                }
        }

    }
    public void stopThreadManager() {
        running = false;
        notifyMe();
    }
	
	@Override
	public synchronized void notifyThreadEnd(long threadNo) {
	    TaskThread taskThread = threadActiveList.get(Long.valueOf(threadNo));
	    if(taskThread != null){
	        threadActiveList.remove(Long.valueOf(threadNo));
	    }
	    notifyMe();
	}
    
}
